package cn.hj.domain.strategy.service.raffle;

import cn.hj.domain.activity.repository.IActivityRepository;
import cn.hj.domain.strategy.adapter.repository.IStrategyRepository;
import cn.hj.domain.strategy.model.entity.StrategyAwardEntity;
import cn.hj.domain.strategy.model.valobj.RuleTreeVO;
import cn.hj.domain.strategy.model.valobj.RuleWeightVO;
import cn.hj.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import cn.hj.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import cn.hj.domain.strategy.service.*;
import cn.hj.domain.strategy.service.Armory.StrategyArmoryDispatch;
import cn.hj.domain.strategy.service.rule.chain.ILogicChain;
import cn.hj.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import cn.hj.domain.strategy.service.rule.filter.factory.DefaultLogicFactory;
import cn.hj.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import cn.hj.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@Primary
public class DefaultRaffleStrategy extends AbstractRaffleStrategy implements IRaffleAward, IRaffleStock , IRaffleRule {




    @Resource
    private DefaultChainFactory chainFactory;

    @Resource
    private IActivityRepository activityRepository;

    public DefaultRaffleStrategy(IStrategyRepository strategyRepository, StrategyArmoryDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) {
        super(strategyRepository, strategyDispatch, defaultChainFactory, defaultTreeFactory);
    }


    @Override
    public DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId) {
        ILogicChain logicChain = chainFactory.openChain(strategyId);
        return logicChain.logic(strategyId, userId);
    }

    @Override
    public DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId) {
        StrategyAwardRuleModelVO strategyAwardRuleModelVO = strategyRepository.queryStrategyAwardRuleModelVO(strategyId, awardId);
        //如果没配置规则
        if (strategyAwardRuleModelVO == null){
            return DefaultTreeFactory.StrategyAwardVO.builder()
                    .awardId(awardId)
                    .build();
        }
        RuleTreeVO ruleTreeVO = strategyRepository.queryRuleTreeVOByTreeId(strategyAwardRuleModelVO.getRuleModels());
        if (ruleTreeVO == null) {
            throw new RuntimeException("存在抽奖策略配置的规则模型 Key，未在库表 rule_tree、rule_tree_node、rule_tree_line 配置对应的规则树信息 " + strategyAwardRuleModelVO.getRuleModels());
        }
        IDecisionTreeEngine treeEngine = defaultTreeFactory.openLogicTree(ruleTreeVO);
        return treeEngine.process(userId, strategyId, awardId,null);
    }

    @Override
    public StrategyAwardStockKeyVO getQueueValue() {
        return strategyRepository.getQueueValue();
    }

    @Override
    public void updateStock(Long strategyId, Integer awardId) {
        strategyRepository.updateStock(strategyId, awardId);
    }


    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardList(Long strategyId) {
        return strategyRepository.queryStrategyAwardList(strategyId);
    }

    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardListByActivityId(Long activityId) {
        Long strategyId = activityRepository.queryStrategyIdByActivityId(activityId);
        return queryRaffleStrategyAwardList(strategyId);
    }

    @Override
    public Map<String, Integer> queryAwardRuleLockCount(String[] treeIds) {
        return strategyRepository.queryAwardRuleLockCount(treeIds);
    }

    @Override
    public List<RuleWeightVO> queryAwardRuleWeight(Long strategyId) {
        return strategyRepository.queryAwardRuleWeight(strategyId);
    }

    @Override
    public List<RuleWeightVO> queryAwardRuleWeightByActivityId(Long activityId) {
        Long strategyId = activityRepository.queryStrategyIdByActivityId(activityId);
        return strategyRepository.queryAwardRuleWeight(strategyId);
    }
}
